package mtn.bowen.yan.server.fx;

import com.alibaba.druid.util.StringUtils;
import com.gn.decorator.GNDecorator;
import com.gn.decorator.options.ButtonType;
import com.google.common.collect.Lists;
import javafx.application.Platform;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import mtn.bowen.yan.server.controller.MainController;
import mtn.bowen.yan.server.enums.DishesKindEnum;
import mtn.bowen.yan.server.enums.DishesTypeEnum;
import mtn.bowen.yan.server.enums.WeekEnum;
import mtn.bowen.yan.server.model.WeekRecipe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author <a href=mailto:yanbowen90@foxmail.com> bowen.yan </a>
 * @version 1.0
 * @description: Manages switching Scenes on the Primary Stage
 * @date 2021-10-21 11:58 PM
 */
public class StageManager {

    private final static Logger LOGGER = LoggerFactory.getLogger(StageManager.class);

    /**
     * 编辑状态下，类型和星期选择集合
     */
    private static Map<String, String> typeAndWeekMap = new ConcurrentHashMap<>();

    /**
     * 编辑状态下，种类集合
     */
    private static Map<DishesTypeEnum, Map<DishesKindEnum, Integer>> dishesTypeKindMap = new ConcurrentHashMap<>();

    private static Map<DishesKindEnum, Integer> kindMap = new ConcurrentHashMap<>();

    /**
     * 图片路径集合
     */
    private static Map<String, File> foodPictures = new ConcurrentHashMap<>();

    /**
     * 场景集合
     */
    private static Map<String, Stage> stageMap = new ConcurrentHashMap<>();

    /**
     * 主界面StackPane集合
     */
    private static Map<String, StackPane> parentStackPaneMap = new ConcurrentHashMap<>();

    /**
     * 主界面Parent集合
     */
    private static Map<String, Parent> parentMap = new ConcurrentHashMap<>();

    private final Stage primaryStage;

    private final SpringFXMLLoader springFXMLLoader;

    private final GNDecorator decorator;

    private static ExecutorService executor = Executors.newSingleThreadExecutor();

    /**
     * 待删除菜品集合
     */
    private static Map<String, String> deleteRecipeMap = new ConcurrentHashMap<>();

    /**
     * 设置每天食谱集合
     */
    private static Map<String, WeekRecipe> addWeekRecipeMap = new ConcurrentHashMap<>();

    /**
     * 待投票建议集合
     */
    private static Map<String, String> pollsSuggestMap = new ConcurrentHashMap<>();

    public StageManager(SpringFXMLLoader springFXMLLoader, Stage stage, GNDecorator decorator) {
        this.springFXMLLoader = springFXMLLoader;
        this.primaryStage = stage;
        this.decorator = decorator;

        // set decorator
        decorator.setTitle("大渡河神炮旅智能菜谱系统（服务端）");
//		      decorator.setIcon(null);
        decorator.addButton(ButtonType.FULL_EFFECT);
        decorator.initTheme(GNDecorator.Theme.DEFAULT);
        decorator.getStage().setOnCloseRequest(event -> {
            this.closeAllPopups();
            Platform.exit();
        });
        decorator.getScene().getStylesheets().addAll(getClass().getResource("/styles/theme/fonts.css").toExternalForm(),
                getClass().getResource("/styles/theme/material-color.css").toExternalForm(),
                getClass().getResource("/styles/theme/skeleton.css").toExternalForm(),
                getClass().getResource("/styles/theme/light.css").toExternalForm(),
                getClass().getResource("/styles/theme/bootstrap.css").toExternalForm(),
                getClass().getResource("/styles/theme/shape.css").toExternalForm(),
                getClass().getResource("/styles/theme/typographic.css").toExternalForm(),
                getClass().getResource("/styles/theme/helpers.css").toExternalForm(),
                getClass().getResource("/styles/theme/master.css").toExternalForm());
        decorator.setMaximized(true);
        decorator.getStage().getIcons().add(new Image("/icons/jjxy.png"));

        //初始化星期选择
        typeAndWeekMap.put("Week", WeekEnum.MONDAY.getMsg());
        //初始化类型选择
        typeAndWeekMap.put("Type", DishesTypeEnum.BREAKFAST.getMsg());

        //初始化图片存储路径
        String path = this.getClass().getResource("/picture").getPath();
        StageManager.putFoodPictures("AllPicture", new File(path));

    }

    /**
     * replace content for primary stage
     *
     * @param view
     */
    public void switchScene(final FxmlView view) {
        Parent viewRootNodeHierarchy = loadViewNodeHierarchy(view.fxml());
        decorator.setContent(viewRootNodeHierarchy);
    }

    /**
     * replace content for pane
     *
     * @param view
     * @param body
     */
    public void switchContent(final FxmlView view, ScrollPane body) {
        Parent viewRootNodeHierarchy = loadViewNodeHierarchy(view.fxml());
        body.setContent(viewRootNodeHierarchy);
    }

    /**
     * show
     *
     * @param view
     */
    public void showPopWindow(final FxmlView view) {
        try {
            Parent viewRootNodeHierarchy = loadViewNodeHierarchy(view.fxml());
            Scene scene = prepareScene(viewRootNodeHierarchy);
            primaryStage.setTitle(view.title());
            primaryStage.setScene(scene);
            primaryStage.setHeight(600d);
            primaryStage.setWidth(1000d);
            primaryStage.centerOnScreen();
            primaryStage.show();
        } catch (Exception exception) {
            logAndExit("Unable to show scene for title" + view.title(), exception);
        }
    }

    public Stage showPopWindowOnTop(final FxmlView view) {
        try {
            Parent viewRootNodeHierarchy = loadViewNodeHierarchy(view.fxml());
            Scene scene = prepareScene(viewRootNodeHierarchy);
            primaryStage.setTitle(view.title());
            primaryStage.setScene(scene);
            primaryStage.setHeight(720d);
            primaryStage.setWidth(485d);
            primaryStage.centerOnScreen();
            //窗口置顶
            primaryStage.setAlwaysOnTop(true);
            primaryStage.initStyle(StageStyle.UNDECORATED);
            primaryStage.show();
        } catch (Exception exception) {
            logAndExit("Unable to show scene for title" + view.title(), exception);
        }
        return primaryStage;
    }

    private Scene prepareScene(Parent rootnode) {
        Scene scene = primaryStage.getScene();

        if (scene == null) {
            scene = new Scene(rootnode);
        }
        scene.setRoot(rootnode);
        return scene;
    }

    /**
     * Loads the object hierarchy from a FXML document and returns to root node of
     * that hierarchy.
     *
     * @return Parent root node of the FXML document hierarchy
     */
    private Parent loadViewNodeHierarchy(String fxmlFilePath) {
        Parent rootNode = null;
        try {
            rootNode = springFXMLLoader.load(fxmlFilePath);
            Objects.requireNonNull(rootNode, "A Root FXML node must not be null");
        } catch (Exception exception) {
            logAndExit("Unable to load FXML view" + fxmlFilePath, exception);
        }
        return rootNode;
    }

    private void logAndExit(String errorMsg, Exception exception) {
        LOGGER.error(errorMsg, exception, exception.getCause());
        Platform.exit();
    }

    public GNDecorator getDecorator() {
        return decorator;
    }

    public void closeAllPopups() {
        if (MainController.popConfig.isShowing()) {
            MainController.popConfig.hide();
        }
        if (MainController.popup.isShowing()) {
            MainController.popup.hide();
        }
    }

    public void showDecorator() {
        decorator.show();
    }

    /**
     * 根据key存放Scene
     */
    public static void put(String key, Stage stage) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (Objects.isNull(stage)) {
            throw new RuntimeException("scene不为空!");
        }
        stageMap.put(key, stage);
    }

    /**
     * 根据key获取Scene
     */
    public static Stage getStage(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        return stageMap.get(key);
    }

    public static String getTypeAndWeekMap(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        return typeAndWeekMap.get(key);
    }

    public static void putTypeAndWeekMap(String key, String value) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (Objects.isNull(value)) {
            throw new RuntimeException("value不为空!");
        }
        typeAndWeekMap.put(key, value);
    }

    public static Map<DishesKindEnum, Integer> getDishesTypeKindMap(DishesTypeEnum key) {
        return dishesTypeKindMap.get(key);
    }

    public static void putDishesTypeKindMap(DishesTypeEnum key, Map<DishesKindEnum, Integer> map) {

        dishesTypeKindMap.put(key, map);
    }

    public static Integer getKindMapValue(DishesKindEnum key) {
        return kindMap.get(key);
    }

    public static Map<DishesKindEnum, Integer> getKindMap() {
        return kindMap;
    }

    public static void putKindMap(DishesKindEnum key, Integer value) {
        if (Objects.isNull(value)) {
            throw new RuntimeException("value不为空!");
        }
        kindMap.put(key, value);
    }

    public static File getFoodPictures(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        return foodPictures.get(key);
    }

    public static void putFoodPictures(String key, File value) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (Objects.isNull(value)) {
            throw new RuntimeException("value不为空!");
        }
        foodPictures.put(key, value);
    }

    public static StackPane getParentStackPaneMap(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        return parentStackPaneMap.get(key);
    }

    public static void putParentStackPaneMap(String key, StackPane stackPane) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (Objects.isNull(stackPane)) {
            throw new RuntimeException("parent不为空!");
        }
        parentStackPaneMap.put(key, stackPane);
    }

    public static Parent getParentLoadMap(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        return parentMap.get(key);
    }

    public static void putParentLoadMap(String key, Parent parent) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (Objects.isNull(parent)) {
            throw new RuntimeException("parent不为空!");
        }
        parentMap.put(key, parent);
    }

    public static ExecutorService getExecutor() {
        return executor;
    }

    public static Map<String, String> getDeleteRecipeMap() {
        return deleteRecipeMap;
    }

    public static void deleteRecipeMapDropIfExists(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (deleteRecipeMap.containsKey(key)) {
            deleteRecipeMap.remove(key);
        } else {
            deleteRecipeMap.put(key, "");
        }
    }

    public static Map<String, WeekRecipe> getAddWeekRecipeMap() {
        return addWeekRecipeMap;
    }

    public static void addWeekRecipeMapDropIfExists(String key, WeekRecipe weekRecipe) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (addWeekRecipeMap.containsKey(key)) {
            addWeekRecipeMap.remove(key);
        } else {
            addWeekRecipeMap.put(key, weekRecipe);
        }
    }

    public static Map<String, String> getPollsSuggestMap() {
        return pollsSuggestMap;
    }

    public static void pollsSuggestMapDropIfExists(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new RuntimeException("key不为空!");
        }
        if (pollsSuggestMap.containsKey(key)) {
            pollsSuggestMap.remove(key);
        } else {
            pollsSuggestMap.put(key, "");
        }
    }
}

